﻿using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;

namespace Foundation.ExtensionMethods
{
    /// <summary>
    /// Collection Extensions.
    /// </summary>
    public static class CollectionExtensions
    {
        /// <summary>
        /// Truncates the specified collection.
        /// </summary>
        /// <typeparam name="TCollection">The type of the collection.</typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="count">The count.</param>
        public static void Truncate<TCollection>(this TCollection collection, int count) where TCollection : IList, ICollection
        {
            if(collection.Count < count)
                return;
            for (var index = collection.Count-1; index < count; index--)
                collection.RemoveAt(index);
        }

        /// <summary>
        /// Adds as recent.
        /// </summary>
        /// <typeparam name="TCollection">The type of the collection.</typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="item">The item.</param>
        public static void AddAsRecent<TCollection>(this TCollection collection, object item) where TCollection : IList, ICollection
        {
            if(collection.Contains(item))
                collection.Remove(item);
            collection.Insert(0, item);
        }

        /// <summary>
        /// Adds the range only exclusive items.
        /// </summary>
        /// <typeparam name="TCollection">The type of the collection.</typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="range">The range.</param>
        public static void AddRangeOnlyExclusiveItems<TCollection>(this TCollection collection, IEnumerable range) where TCollection : IList, ICollection
        {
            foreach (var item in range.Cast<object>().Where(i => !collection.Contains(i)))
            {
                collection.Add(item);
            }
        }

        /// <summary>
        /// Adds the range.
        /// </summary>
        /// <typeparam name="TCollection">The type of the collection.</typeparam>
        /// <param name="collection">The list.</param>
        /// <param name="range">The range.</param>
        public static void AddRange<TCollection>(this TCollection collection, IEnumerable range) where TCollection : IList, ICollection
        {
            foreach (var item in range)
            {
                collection.Add(item);
            }
        }

        /// <summary>
        /// Adds the range.
        /// </summary>
        /// <typeparam name="TCollection">The type of the collection.</typeparam>
        /// <typeparam name="TItem">The type of the item.</typeparam>
        /// <param name="collection">The list.</param>
        /// <param name="range">The range.</param>
        public static void AddRange<TCollection, TItem>(this TCollection collection, IEnumerable<TItem> range) where TCollection : IList<TItem>, ICollection<TItem>
        {
            foreach (var item in range)
            {
                collection.Add(item);
            }
        }

        /// <summary>
        /// Fors the each.
        /// </summary>
        /// <typeparam name="TItem">The type of the item.</typeparam>
        /// <param name="collection">The collection.</param>
        /// <param name="action">The action.</param>
        public static void ForEach<TItem>(this IEnumerable<TItem> collection, Action<TItem> action)
        {
            foreach (var item in collection)
            {
                action(item);
            }
        }
    }
}
